﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;
using DevExpress.XtraEditors.ScrollHelpers;
using HoNSharp;
using LibBot;

namespace NewerthBot
{
    public partial class Main : Form
    {
        int CurrentChannel;

        List<HoNBuddy> BuddyList = new List<HoNBuddy>();
        List<HoNUser> ClanRoster = new List<HoNUser>();
        List<string> Chatrooms = new List<string>();

        RadioButton[] radChannel = new RadioButton[9];
        RichTextBox[] txtChat = new RichTextBox[9];
        ScrollBarAPIHelper[] txtScroll = new ScrollBarAPIHelper[9];
        UInt32[] ChannelID = new UInt32[9];
        ListView[] ChannelUsers = new ListView[9];
        Dictionary<UInt32, HoNOper[]> ChannelOpers = new Dictionary<uint, HoNOper[]>();

        ListViewSorter lstSorter;

        #region Scrollbars
        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("User32.dll", EntryPoint = "GetScrollPos")]
        static extern int GetScrollPos(IntPtr hWnd, int nBar);

        const int WM_VSCROLL = 0x115;
        const int SB_BOTTOM = 7;
        const int SB_VERT = 1;
        #endregion

        #region Colors
        Color colorClan = Color.FromArgb(85, 107, 171);
        #endregion

        #region Form Events
        public Main()
        {
            InitializeComponent();
            radChannel[0] = radStatus;
            radChannel[1] = radChannel1;
            radChannel[2] = radChannel2;
            radChannel[3] = radChannel3;
            radChannel[4] = radChannel4;
            radChannel[5] = radChannel5;
            radChannel[6] = radChannel6;
            radChannel[7] = radChannel7;
            radChannel[8] = radChannel8;

            txtChat[0] = txtStatus;
            txtChat[1] = txtChat1;
            txtChat[2] = txtChat2;
            txtChat[3] = txtChat3;
            txtChat[4] = txtChat4;
            txtChat[5] = txtChat5;
            txtChat[6] = txtChat6;
            txtChat[7] = txtChat7;
            txtChat[8] = txtChat8;

            lstSorter = new ListViewSorter();
            lstPlayers.ListViewItemSorter = lstSorter;

            barFilter.ColorScheme.ItemCheckedBackground2 = Color.Transparent;
            barFilter.ColorScheme.ItemHotBackground2 = Color.Transparent;
            barFilter.ColorScheme.ItemPressedBackground2 = Color.Transparent;

            for (int count = 0; count <= 8; count++)
            {
                txtScroll[count] = new ScrollBarAPIHelper();
                ChannelUsers[count] = new ListView();
                ChannelID[count] = 32768;
                txtScroll[count].Init(txtChat[count], txtChat[count].Parent);
                txtScroll[count].UpdateScrollBars();
            }
        }

        private void Main_Load(object sender, EventArgs e)
        {
            System.Net.WebClient wc = new System.Net.WebClient();

            switch (Program.Core.CheckForUpdates())
            {
                case Core.UpdateType.UPDATE_FULL:
                    if (MessageBox.Show(this, "An update is available, would you like to download it?", "NewerthBot", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        wc.DownloadFile("http://dl.dropbox.com/u/2683550/Heroes%20of%20Newerth/NewerthBot/NewerthUpdater.exe", Application.StartupPath + "/NewerthUpdater.exe");                        
                        Process.Start(Application.StartupPath + "/NewerthUpdater.exe");
                        Application.Exit();
                    }
                    break;

                case Core.UpdateType.UPDATE_UPDATER:
                    if (MessageBox.Show(this, "An update is available, would you like to download it?", "NewerthBot", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        wc.DownloadFile("http://dl.dropbox.com/u/2683550/Heroes%20of%20Newerth/NewerthBot/NewerthUpdater.exe", Application.StartupPath + "/NewerthUpdater.exe");
                        Process.Start(Application.StartupPath + "/NewerthUpdater.exe");
                        Application.Exit();
                    }
                    break;

                case Core.UpdateType.UPDATE_FILES:
                    if (MessageBox.Show(this, "An update is available, would you like to download it?", "NewerthBot", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        Process.Start(Application.StartupPath + "/NewerthUpdater.exe");
                        Application.Exit();
                    }
                    break;
            }
        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!NewerthBot.Properties.Settings.Default.RememberUser)
            {
                NewerthBot.Properties.Settings.Default.Username = "";
                NewerthBot.Properties.Settings.Default.Password = "";
            }

            NewerthBot.Properties.Settings.Default.Save();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (btnConnect.Text == "Connect")
            {
                Login frmLogin = new Login();

                if (frmLogin.ShowDialog(this) == DialogResult.OK)
                {
                    btnConnect.Text = "Disconnect";
                    barFilter.Enabled = true;
                    btnLeaveChannel.Enabled = true;
                    txtSendMessage.Enabled = true;
                    txtStatus.Text = "";

                    Program.Core = new Core();
                    Program.Core.ScanPlugins();
                    Program.Core.ScanAdmins();
                    Program.Core.onBuddyWhisper += new Core.BuddyWhisperEventHandler(Core_onBuddyWhisper);
                    Program.Core.onChannelMessage += new Core.ChannelMessageEventHandler(Core_onChannelMessage);
                    Program.Core.onClanMessage += new Core.ClanMessageEventHandler(Core_onClanMessage);
                    Program.Core.onCommand += new Core.CommandEventHandler(Core_onCommand);
                    Program.Core.onDiceRoll += new Core.DiceRollEventHandler(Core_onDiceRoll);
                    Program.Core.onDisconnect += new Core.DisconnectEventHandler(Core_onDisconnect);
                    Program.Core.onEmote += new Core.EmoteEventHandler(Core_onEmote);
                    Program.Core.onInitialStatus += new Core.InitialStatusEventHandler(Core_onInitialStatus);
                    Program.Core.onInstantMessage += new Core.InstantMessageEventHandler(Core_onInstantMessage);
                    Program.Core.onLeaveChannel += new Core.LeaveChannelEventHandler(Core_onLeaveChannel);
                    Program.Core.onLoginComplete += new Core.LoginCompleteEventHandler(Core_onLoginComplete);
                    Program.Core.onNewChannel += new Core.NewChannelEventHandler(Core_onNewChannel);
                    Program.Core.onPlayerDemoted += new Core.PlayerDemotedEventHandler(Core_onPlayerDemoted);
                    Program.Core.onPlayerJoinedChannel += new Core.PlayerJoinedChannelEventHandler(Core_onPlayerJoinedChannel);
                    Program.Core.onPlayerLeftChannel += new Core.PlayerLeftChannelEventHandler(Core_onPlayerLeftChannel);
                    Program.Core.onPlayerPromoted += new Core.PlayerPromotedEventHandler(Core_onPlayerPromoted);
                    Program.Core.onPluginConflict += new Core.PluginConflictEventHandler(Core_onPluginConflict);
                    Program.Core.onSendChannelMessage += new Core.SendChannelMessageEventHandler(Core_onSendChannelMessage);
                    Program.Core.onSendClanMessage += new Core.SendClanMessageEventHandler(Core_onSendClanMessage);
                    Program.Core.onSendEmote += new Core.SendEmoteEventHandler(Core_onSendEmote);
                    Program.Core.onSendInstantMessage += new Core.SendInstantMessageEventHandler(Core_onSendInstantMessage);
                    Program.Core.onSendWhisper += new Core.SendWhisperEventHandler(Core_onSendWhisper);
                    Program.Core.onSlashCommand += new Core.SlashCommandEventHandler(Core_onSlashCommand);
                    Program.Core.onStatusUpdate += new Core.StatusUpdateEventHandler(Core_onStatusUpdate);
                    Program.Core.onTopicChanged += new Core.TopicChangedEventHandler(Core_onTopicChanged);
                    Program.Core.onWhisper += new Core.WhisperEventHandler(Core_onWhisper);
                    Program.Core.Login(NewerthBot.Properties.Settings.Default.Username, NewerthBot.Properties.Settings.Default.Password);

                    txtSendMessage.Focus();
                }
            }
            else
            {
                Program.Core.Disconnect();

                lstPlayers.Clear();
                lstPlayers.Columns.Add("", 165);

                for (int count = 0; count <= 8; count++)
                {
                    radChannel[count].Visible = false;
                    txtChat[count].Text = "";
                    ChannelUsers[count].Clear();
                }

                radStatus.Visible = true;
                radStatus.Checked = true;

                btnConnect.Text = "Connect";
                barFilter.Enabled = false;
                btnLeaveChannel.Enabled = false;
                txtSendMessage.Enabled = false;

                txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Disconnected from the server.");
            }
        }

        private void btnAbout_Click(object sender, EventArgs e)
        {
            About frmAbout = new About();
            frmAbout.ShowDialog(this);
        }

        private void btnLeaveChannel_Click(object sender, EventArgs e)
        {
            if (CurrentChannel > 1)
            {
                Program.Core.onLeaveChannel -= Core_onLeaveChannel;
                Program.Core.LeaveChannel(radChannel[CurrentChannel].Text);
                Program.Core.onLeaveChannel += Core_onLeaveChannel;

                txtChat[CurrentChannel].Clear();
                radChannel[CurrentChannel].Text = "";
                radChannel[CurrentChannel].Visible = false;
                CurrentChannel--;
                txtChat[CurrentChannel].BringToFront();
                radChannel[CurrentChannel].Checked = true;
            }
        }

        private void btnSendMessage_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtSendMessage.Text))
            {
                Program.Core.SendChannelMessage(ChannelID[CurrentChannel], txtSendMessage.Text);
                txtSendMessage.Text = "";
            }
        }

        private void txtSendMessage_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter && btnSendMessage.Enabled)
            {
                e.SuppressKeyPress = true;

                if (!string.IsNullOrEmpty(txtSendMessage.Text))
                {
                    Program.Core.SendChannelMessage(ChannelID[CurrentChannel], txtSendMessage.Text);
                    txtSendMessage.Text = "";
                }
            }
        }

        private void txtSendMessage_TextChanged(object sender, EventArgs e)
        {
            if (txtSendMessage.Text != "")
            {
                if (txtSendMessage.Text == "/r ")
                {
                    switch (Program.Core.LastMessageType)
                    {
                        case Core.MessageType.BUDDY_WHISPER:
                            txtSendMessage.Text = "/b m ";
                            break;

                        case Core.MessageType.CLAN_MESSAGE:
                            txtSendMessage.Text = "/c m ";
                            break;

                        case Core.MessageType.WHISPER:
                            txtSendMessage.Text = "/w " + Program.Core.LastWhisper + " ";
                            break;
                    }
                }

                btnSendMessage.Enabled = true;
            }
            else
            {
                btnSendMessage.Enabled = false;
            }
        }

        private void txtChat_TextChanged(object sender, EventArgs e)
        {
            RichTextBox txtChat = (RichTextBox)sender;

            if (txtChat.Text != "")
            {
                string[] lines = txtChat.Lines;
                string originalmessage = lines[lines.Length - 1];
                string message = lines[lines.Length - 1];

                int r = 0;
                int g = 0;
                int b = 0;
                string pattern = @"\^\d{3}";
                string badpattern = @"\^\d{3}\^\d{3}";
                Match match;

                // Replace text colors with RGB colors
                message = message.Replace("^w", "^999");
                message = message.Replace("^r", "^900");
                message = message.Replace("^g", "^090");
                message = message.Replace("^b", "^009");
                message = message.Replace("^c", "^099");
                message = message.Replace("^y", "^990");
                message = message.Replace("^m", "^909");
                message = message.Replace("^v", "^444");
                message = message.Replace("^!b", "^029");
                message = message.Replace("^!t", "^176");
                message = message.Replace("^!p", "^304");
                message = message.Replace("^!o", "^851");
                message = message.Replace("^!i", "^836");
                message = message.Replace("^!v", "^555");
                message = message.Replace("^!g", "^032");
                message = message.Replace("^!n", "^310");
                message = message.Replace("^!y", "^990");

                // Uppercase
                message = message.Replace("^W", "^999");
                message = message.Replace("^R", "^900");
                message = message.Replace("^G", "^090");
                message = message.Replace("^B", "^009");
                message = message.Replace("^C", "^099");
                message = message.Replace("^Y", "^990");
                message = message.Replace("^M", "^909");
                message = message.Replace("^V", "^444");
                message = message.Replace("^!B", "^029");
                message = message.Replace("^!T", "^176");
                message = message.Replace("^!P", "^304");
                message = message.Replace("^!O", "^851");
                message = message.Replace("^!I", "^836");
                message = message.Replace("^!V", "^555");
                message = message.Replace("^!G", "^032");
                message = message.Replace("^!N", "^310");
                message = message.Replace("^!Y", "^990");

                match = Regex.Match(message, badpattern);

                while (match.Success)
                {
                    message = message.Remove(message.IndexOf(match.Value), 4);
                    match = match.NextMatch();
                }

                match = Regex.Match(message, pattern);

                if (match.Success)
                {
                    if (message.StartsWith(match.Value))
                    {
                        foreach (string text in Regex.Split(message, pattern))
                        {
                            if (text != "")
                            {
                                if (match.Value != "")
                                {

                                    r = Convert.ToInt32(match.Value[1].ToString()) * (255 / 9);
                                    g = Convert.ToInt32(match.Value[2].ToString()) * (255 / 9);
                                    b = Convert.ToInt32(match.Value[3].ToString()) * (255 / 9);
                                }

                                txtChat.SelectionColor = Color.FromArgb(r, g, b);
                                txtChat.TextChanged -= txtChat_TextChanged;
                                txtChat.AppendText(text);
                                txtChat.TextChanged += txtChat_TextChanged;

                                match = match.NextMatch();
                            }
                        }
                    }
                    else
                    {
                        foreach (string text in Regex.Split(message, pattern))
                        {
                            if (text != "")
                            {
                                txtChat.SelectionColor = Color.FromArgb(r, g, b);
                                txtChat.TextChanged -= txtChat_TextChanged;
                                txtChat.AppendText(text);
                                txtChat.TextChanged += txtChat_TextChanged;

                                if (match.Value != "")
                                {
                                    r = Convert.ToInt32(match.Value[1].ToString()) * (255 / 9);
                                    g = Convert.ToInt32(match.Value[2].ToString()) * (255 / 9);
                                    b = Convert.ToInt32(match.Value[3].ToString()) * (255 / 9);
                                }

                                match = match.NextMatch();
                            }
                        }
                    }

                    txtChat.TextChanged -= txtChat_TextChanged;
                    txtChat.Rtf = txtChat.Rtf.Remove(txtChat.Rtf.LastIndexOf(originalmessage), originalmessage.Length);
                    txtChat.TextChanged += txtChat_TextChanged;
                }
                else
                {
                    txtChat.SelectionColor = Color.White;
                    txtChat.TextChanged -= txtChat_TextChanged;
                    txtChat.AppendText(message);
                    txtChat.TextChanged += txtChat_TextChanged;
                }
            }

            IntPtr ptrWparam = new IntPtr(SB_BOTTOM);
            IntPtr ptrLparam = new IntPtr(0);
            SendMessage(txtChat.Handle, WM_VSCROLL, ptrWparam, ptrLparam);
        }

        private void txtChat_VScroll(object sender, EventArgs e)
        {
            RichTextBox _txtChat = (RichTextBox)sender;

            for (int count = 0; count <= 8; count++)
            {
                if (txtChat[count] == sender)
                {
                    txtScroll[count].VScroll.Value = GetScrollPos(_txtChat.Handle, SB_VERT);
                    txtScroll[count].UpdateScrollBars();
                }
            }
        }

        private void btnAutoConnect_CheckedChanged(object sender, EventArgs e)
        {
            if (btnAutoConnect.Checked)
            {
                if (!Chatrooms.Contains(radChannel[CurrentChannel].Text))
                {
                    Program.Core.AddAutoJoin(radChannel[CurrentChannel].Text);
                    Chatrooms.Add(radChannel[CurrentChannel].Text);
                }
            }
            else
            {
                if (Chatrooms.Contains(radChannel[CurrentChannel].Text))
                {
                    Program.Core.RemoveAutoJoin(radChannel[CurrentChannel].Text);
                    Chatrooms.Remove(radChannel[CurrentChannel].Text);
                }
            }
        }

        #region barFilter
        private void btnChannel_CheckedChanged(object sender, EventArgs e)
        {
            if (!btnChannel.Checked && !btnFriends.Checked && !btnClan.Checked)
            {
                btnChannel.CheckedChanged -= btnChannel_CheckedChanged;
                btnChannel.Checked = true;
                btnChannel.CheckedChanged += btnChannel_CheckedChanged;
            }

            if (btnChannel.Checked)
            {
                btnFriends.Checked = false;
                btnClan.Checked = false;

                lstPlayers.Clear();
                lstPlayers.Columns.Add("", 165);
                lstPlayers.SmallImageList = imageList;

                foreach (ListViewItem user in ChannelUsers[CurrentChannel].Items)
                {
                    lstPlayers.Items.Add((ListViewItem)user.Clone());
                }
            }
        }

        private void btnFriends_CheckedChanged(object sender, EventArgs e)
        {
            if (!btnChannel.Checked && !btnFriends.Checked && !btnClan.Checked)
            {
                btnFriends.CheckedChanged -= btnFriends_CheckedChanged;
                btnFriends.Checked = true;
                btnFriends.CheckedChanged += btnFriends_CheckedChanged;
            }

            if (btnFriends.Checked)
            {
                btnChannel.Checked = false;
                btnClan.Checked = false;

                lstPlayers.Clear();
                lstPlayers.Columns.Add("", 165);
                lstPlayers.SmallImageList = imageList2;

                foreach (HoNBuddy buddy in BuddyList)
                {
                    ListViewItem lvi = new ListViewItem(buddy.Username);
                    lvi.Tag = buddy.UserID;

                    switch (buddy.Status)
                    {
                        case HoNClient.USER_STATUS_ONLINE:
                            lvi.ImageIndex = 2;
                            break;

                        case HoNClient.USER_STATUS_LOBBY:
                        case HoNClient.USER_STATUS_GAME:
                            lvi.ImageIndex = 1;
                            break;

                        case HoNClient.USER_STATUS_OFFLINE:
                            lvi.ImageIndex = 0;
                            break;

                        default:
                            lvi.ImageIndex = 0;
                            break;
                    }

                    lstPlayers.Items.Add(lvi);
                }
            }
        }

        private void btnClan_CheckedChanged(object sender, EventArgs e)
        {
            if (!btnChannel.Checked && !btnFriends.Checked && !btnClan.Checked)
            {
                btnClan.CheckedChanged -= btnClan_CheckedChanged;
                btnClan.Checked = true;
                btnClan.CheckedChanged += btnClan_CheckedChanged;
            }

            if (btnClan.Checked)
            {
                btnChannel.Checked = false;
                btnFriends.Checked = false;

                lstPlayers.Clear();
                lstPlayers.Columns.Add("", 165);
                lstPlayers.SmallImageList = imageList2;

                foreach (HoNUser member in ClanRoster)
                {
                    ListViewItem lvi = new ListViewItem(member.Username);
                    lvi.Tag = member.UserID;

                    switch (member.Status)
                    {
                        case HoNClient.USER_STATUS_ONLINE:
                            lvi.ImageIndex = 2;
                            break;

                        case HoNClient.USER_STATUS_LOBBY:
                        case HoNClient.USER_STATUS_GAME:
                            lvi.ImageIndex = 1;
                            break;

                        case HoNClient.USER_STATUS_OFFLINE:
                            lvi.ImageIndex = 0;
                            break;

                        default:
                            lvi.ImageIndex = 0;
                            break;
                    }

                    lstPlayers.Items.Add(lvi);
                }
            }
        }
        #endregion

        #region radChannels
        private void radStatus_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 0;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radStatus.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);
                        }

                        btnAutoConnect.Enabled = false;
                        txtStatus.BringToFront();
                        pnlNewerthBot.Visible = true;
                        lblChannelName.Text = "";
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);
                }

                btnAutoConnect.Enabled = false;
                txtStatus.BringToFront();
                pnlNewerthBot.Visible = true;
                lblChannelName.Text = "";
            }
        }

        private void radChannel1_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 1;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel1.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[1].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel1.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat1.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel1.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[1].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel1.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat1.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel1.Text;
            }
        }

        private void radChannel2_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 2;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel2.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[2].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel2.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat2.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel2.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[2].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel2.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat2.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel2.Text;
            }
        }

        private void radChannel3_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 3;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel3.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[3].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel3.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat3.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel3.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[3].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel3.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat3.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel3.Text;
            }
        }

        private void radChannel4_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 4;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel4.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[4].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }

                            if (Chatrooms.Contains(radChannel4.Text))
                            {
                                btnAutoConnect.Checked = true;
                            }
                            else
                            {
                                btnAutoConnect.Checked = false;
                            }
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat4.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel4.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[4].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel4.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat4.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel4.Text;
            }
        }

        private void radChannel5_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 5;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel5.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[5].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel5.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat5.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel5.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[5].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel5.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat5.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel5.Text;
            }
        }

        private void radChannel6_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 6;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel6.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[6].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel6.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat6.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel6.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[6].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel6.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat6.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel6.Text;
            }
        }

        private void radChannel7_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 7;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel7.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[7].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel7.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat7.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel7.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[7].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel7.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat7.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel7.Text;
            }
        }

        private void radChannel8_CheckedChanged(object sender, EventArgs e)
        {
            CurrentChannel = 8;
            Program.Core.ChannelID = ChannelID[CurrentChannel];

            if (radChannel8.InvokeRequired)
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        if (btnChannel.Checked)
                        {
                            lstPlayers.Clear();
                            lstPlayers.Columns.Add("", 165);

                            foreach (ListViewItem user in ChannelUsers[8].Items)
                            {
                                lstPlayers.Items.Add((ListViewItem)user.Clone());
                            }
                        }

                        if (Chatrooms.Contains(radChannel8.Text))
                        {
                            btnAutoConnect.Checked = true;
                        }
                        else
                        {
                            btnAutoConnect.Checked = false;
                        }

                        btnAutoConnect.Enabled = true;
                        txtChat8.BringToFront();
                        pnlNewerthBot.Visible = false;
                        lblChannelName.Text = radChannel8.Text;
                    }));
            }
            else
            {
                if (btnChannel.Checked)
                {
                    lstPlayers.Clear();
                    lstPlayers.Columns.Add("", 165);

                    foreach (ListViewItem user in ChannelUsers[8].Items)
                    {
                        lstPlayers.Items.Add((ListViewItem)user.Clone());
                    }
                }

                if (Chatrooms.Contains(radChannel8.Text))
                {
                    btnAutoConnect.Checked = true;
                }
                else
                {
                    btnAutoConnect.Checked = false;
                }

                btnAutoConnect.Enabled = true;
                txtChat8.BringToFront();
                pnlNewerthBot.Visible = false;
                lblChannelName.Text = radChannel8.Text;
            }
        }
        #endregion
        #endregion

        #region Core Events
        void Core_onBuddyWhisper(object sender, BuddyWhisperEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^099<" + e.Username + " Whispered to Buddies> " + e.Message);
                        }));
                }
            }
        }

        void Core_onChannelMessage(object sender, ChannelMessageEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^880" + e.Username + ": ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onClanMessage(object sender, ClanMessageEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^458(Clan) " + e.Username + ": ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onCommand(object sender, CommandEventArgs e)
        {
            string[] parameters;
            UInt32 ChannelID = e.ChannelID;
            List<char> botflags;
            byte flags;
            string whois = "";

            if (e.ChannelName == null)
            {
                ChannelID = this.ChannelID[CurrentChannel];
            }

            switch (e.Command)
            {
                case "admin":
                    if (Program.Core.GetBotFlags(e.Username, 'a'))
                    {
                        if (e.GetParameters(2, out parameters))
                        {
                            XmlDocument xmlDoc = new XmlDocument();
                            XmlNodeList users;

                            xmlDoc.Load(Application.StartupPath + "/newerthbot.xml");
                            users = xmlDoc.SelectNodes("/newerthbot/users/user");

                            switch (parameters[0])
                            {
                                case "add":
                                    if (e.GetParameters(3, out parameters))
                                    {
                                        XmlNode user = xmlDoc.CreateElement("user");
                                        XmlAttribute _botflags = xmlDoc.CreateAttribute("flags");
                                        XmlAttribute _userid = xmlDoc.CreateAttribute("userid");
                                        _botflags.Value = parameters[2];
                                        _userid.Value = Program.Core.GetUserID(parameters[1]).ToString();
                                        user.InnerText = parameters[1];
                                        user.Attributes.Append(_botflags);
                                        xmlDoc.SelectSingleNode("/newerthbot/users").AppendChild(user);
                                    }
                                    break;

                                case "remove":
                                    foreach (XmlNode user in users)
                                    {
                                        if (user.InnerText.ToLower() == parameters[1].ToLower())
                                        {
                                            xmlDoc.SelectSingleNode("/newerthbot/users").RemoveChild(user);
                                            break;
                                        }
                                    }
                                    break;

                                case "update":
                                    if (e.GetParameters(3, out parameters))
                                    {
                                        foreach (XmlNode user in users)
                                        {
                                            if (user.InnerText.ToLower() == parameters[1].ToLower())
                                            {
                                                user.Attributes[0].Value = parameters[2];
                                            }
                                        }
                                    }
                                    break;
                            }
                        }
                    }
                    else
                    {
                        Program.Core.SendChannelMessage(ChannelID, "{0}You do not have permission to use this command, you require the '{1}a{0}' flag!");
                    }                    
                    break;

                case "join":
                    if (Program.Core.GetBotFlags(e.Username, 'c'))
                    {
                        if (!radChannel[8].Visible)
                            Program.Core.JoinChannel(e.Parameters);
                    }
                    else
                    {
                        Program.Core.SendChannelMessage(ChannelID, "{0}You do not have permission to use this command, you require the '{1}c{0}' flag!");
                    }
                    break;

                case "leave":
                    if (Program.Core.GetBotFlags(e.Username, 'c'))
                    {
                        if (e.Parameters != radChannel[1].Text)
                            Program.Core.LeaveChannel(e.Parameters);
                    }
                    else
                    {
                        Program.Core.SendChannelMessage(ChannelID, "{0}You do not have permission to use this command, you require the '{1}c{0}' flag!");
                    }
                    break;

                case "say":
                    if (Program.Core.GetBotFlags(e.Username, 's'))
                    {
                        Program.Core.SendChannelMessage(ChannelID, e.Parameters);
                    }
                    else
                    {
                        Program.Core.SendChannelMessage(ChannelID, "{0}You do not have permission to use this command, you require the '{1}s{0}' flag!");
                    }
                    break;

                case "uptime":
                    TimeSpan span = DateTime.Now - Process.GetCurrentProcess().StartTime;
                    string uptime;

                    if (span.Days > 0)
                    {
                        uptime = "{0}I've been online for {1}" + span.Days + " {0}day(s), {1}" + span.Hours + " {0}hour(s), {1}" + span.Minutes + " {0}minute(s) and {1}" + span.Seconds + " {0}second(s).";
                    }
                    else if (span.Hours > 0)
                    {
                        uptime = "{0}I've been online for {1}" + span.Hours + " {0}hour(s), {1}" + span.Minutes + " {0}minute(s) and {1}" + span.Seconds + " {0}second(s).";
                    }
                    else if (span.Minutes > 0)
                    {
                        uptime = "{0}I've been online for {1}" + span.Minutes + " {0}minute(s) and {1}" + span.Seconds + " {0}second(s).";
                    }
                    else
                    {
                        uptime = "{0}I've been online for {1}" + span.Seconds + " {0}second(s).";
                    }

                    Program.Core.SendChannelMessage(ChannelID, uptime);
                    break;

                case "whoami":
                    botflags = Program.Core.GetBotFlags(e.Username);
                    whois = "{0}You are {1}" + e.Username + " {0}and you have the '{1}";

                    if (botflags.Count > 0)
                    {
                        foreach (char flag in botflags)
                        {
                            whois += flag;
                        }

                        whois += "{0}' flags.";
                        Program.Core.SendChannelMessage(ChannelID, whois);
                    }
                    else
                    {
                        Program.Core.SendChannelMessage(ChannelID, "{0}You are {1}" + e.Username + " {0}and you have {1}no {0}flags.");
                    }
                    break;

                case "whois":
                    if (e.Parameters != "")
                    {
                        if (e.Parameters == Program.Username)
                        {
                            whois = "{0}I'm {1}" + Program.Username + "{0}!";
                        }
                        else
                        {
                            flags = Program.Core.GetFlags(e.Parameters);
                            botflags = Program.Core.GetBotFlags(e.Username);

                            if (botflags.Count > 0)
                            {
                                whois = "{1}" + e.Parameters + " has the '{1}";

                                foreach (char flag in botflags)
                                {
                                    whois += flag;
                                }

                                whois += "{0}' flags.";
                                Program.Core.SendChannelMessage(ChannelID, whois);
                            }
                            else
                            {
                                Program.Core.SendChannelMessage(ChannelID, "{1}" + e.Parameters + " {0}either has {1}no {0}flags or I have not seen him/her before.");
                            }
                        }

                        Program.Core.SendChannelMessage(ChannelID, whois);
                    }
                    break;
            }
        }

        void Core_onDiceRoll(object sender, DiceRollEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^090[" + DateTime.Now.ToShortTimeString() + "] " + e.Message);
                        }));
                }
            }
        }

        void Core_onDisconnect(object sender, DisconnectEventArgs e)
        {
            if (e.Reason == "An established connection was aborted by the software in your host machine")
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        lstPlayers.Clear();
                        lstPlayers.Columns.Add("", 165);

                        for (int count = 0; count <= 8; count++)
                        {
                            radChannel[count].Visible = false;
                            txtChat[count].Text = "";
                            ChannelUsers[count].Clear();
                        }

                        radStatus.Visible = true;
                        radStatus.Checked = true;

                        btnConnect.Text = "Connect";
                        barFilter.Enabled = false;
                        btnLeaveChannel.Enabled = false;
                        txtSendMessage.Enabled = false;

                        txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Disconnected from the server for chat flooding.");
                    }));
            }
            else if (e.Reason != "")
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        lstPlayers.Clear();
                        lstPlayers.Columns.Add("", 165);

                        for (int count = 0; count <= 8; count++)
                        {
                            radChannel[count].Visible = false;
                            txtChat[count].Text = "";
                            ChannelUsers[count].Clear();
                        }

                        radStatus.Visible = true;
                        radStatus.Checked = true;

                        btnConnect.Text = "Connect";
                        barFilter.Enabled = false;
                        btnLeaveChannel.Enabled = false;
                        txtSendMessage.Enabled = false;

                        txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Disconnected from the server: " + e.Reason);
                    }));
            }
        }

        void Core_onEmote(object sender, EmoteEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^838[" + DateTime.Now.ToShortTimeString() + "] " + e.Message);
                        }));
                }
            }
        }

        void Core_onInitialStatus(object sender, InitialStatusEventArgs e)
        {
            HoNBuddy[] _buddies = BuddyList.ToArray();
            HoNUser[] _members = ClanRoster.ToArray();

            for (int count = 0; count <= _buddies.Length - 1; count++)
            {
                foreach (HoNBuddy buddy in e.Buddies)
                {
                    if (_buddies[count].UserID == buddy.UserID)
                    {
                        _buddies[count].GameName = buddy.GameName;
                        _buddies[count].Server = buddy.Server;
                        _buddies[count].Status = buddy.Status;
                    }
                }
            }

            BuddyList.Clear();
            BuddyList.AddRange(_buddies);

            for (int count = 0; count <= _members.Length - 1; count++)
            {
                foreach (HoNBuddy buddy in e.Buddies)
                {
                    if (_members[count].UserID == buddy.UserID)
                    {
                        _members[count].Status = buddy.Status;
                    }
                }
            }

            ClanRoster.Clear();
            ClanRoster.AddRange(_members);
        }

        void Core_onInstantMessage(object sender, InstantMessageEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^940(IM from " + e.Username + ") ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onLeaveChannel(object sender, LeaveChannelEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Text == e.ChannelName)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].Clear();
                            ChannelID[count] = 32768;
                            radChannel[count].Text = "";
                            radChannel[count].Visible = false;

                            for (int i = count + 1; i <= 8; i++)
                            {
                                if (radChannel[i].Visible)
                                {
                                    ChannelID[i - 1] = ChannelID[i];

                                    txtChat[i - 1].TextChanged -= txtChat_TextChanged;
                                    txtChat[i - 1].Rtf = txtChat[i].Rtf;
                                    txtChat[i - 1].TextChanged += txtChat_TextChanged;
                                    txtChat[i].Clear();

                                    ChannelUsers[i - 1].Clear();

                                    foreach (ListViewItem item in ChannelUsers[i].Items)
                                    {
                                        ChannelUsers[i - 1].Items.Add((ListViewItem)item.Clone());
                                    }

                                    radChannel[i - 1].Text = radChannel[i].Text;
                                    radChannel[i - 1].Visible = true;
                                    radChannel[i].Visible = false;
                                }
                                else
                                {
                                    break;
                                }
                            }

                            if (CurrentChannel >= count)
                            {
                                CurrentChannel--;
                                radChannel[CurrentChannel].Checked = true;
                            }
                        }));

                    break;
                }
            }
        }

        void Core_onLoginComplete(object sender, LoginCompleteEventArgs e)
        {
            if (e.IsLoggedIn)
            {
                Program.Username = e.Message;
                Program.UserID = e.UserID;
                BuddyList = e.BuddyList;
                ClanRoster = e.ClanRoster;
                Chatrooms = e.Chatrooms;

                this.Invoke(new EventHandler(
                    delegate
                    {
                        btnSendMessage.Enabled = true;
                        txtSendMessage.Enabled = true;

                        txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Logged in as " + Program.Username);

                        btnConnect.Text = "Disconnect";
                    }));

                foreach (string chatroom in Chatrooms)
                {
                    Program.Core.JoinChannel(chatroom);
                }
            }
            else
            {
                this.Invoke(new EventHandler(
                    delegate
                    {
                        txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + e.Message);
                    }));
            }
        }

        void Core_onNewChannel(object sender, NewChannelEventArgs e)
        {
            ListViewItem lvi;

            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible == false)
                {
                    if (!ChannelOpers.ContainsKey(e.ChannelID))
                    {
                        ChannelOpers.Add(e.ChannelID, e.Operators);
                    }
                    else
                    {
                        ChannelOpers.Remove(e.ChannelID);
                        ChannelOpers.Add(e.ChannelID, e.Operators);
                    }

                    foreach (HoNUser user in e.Users)
                    {
                        lvi = new ListViewItem(user.Username);
                        lvi.Tag = user.UserID;

                        if (Convert.ToBoolean(user.Flags & HoNClient.USER_FLAG_S2))
                        {
                            switch (user.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(253, 0, 0);
                                            lvi.ImageIndex = 4;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(118, 0, 0);
                                            lvi.ImageIndex = 4;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;
                            }
                        }
                        else if (Convert.ToBoolean(user.Flags & HoNClient.USER_FLAG_PURCHASED))
                        {
                            switch (user.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                            lvi.ImageIndex = 2;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                            lvi.ImageIndex = 2;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;
                            }
                        }
                        else
                        {
                            switch (user.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                            lvi.ImageIndex = 1;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    this.Invoke(new EventHandler(
                                        delegate
                                        {
                                            lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                            lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                            lvi.ImageIndex = 0;

                                            ChannelUsers[count].Items.Add(lvi);
                                        }));
                                    break;
                            }
                        }
                    }

                    foreach (HoNOper oper in e.Operators)
                    {
                        foreach (ListViewItem user in ChannelUsers[count].Items)
                        {
                            if ((UInt32)user.Tag == oper.OperID)
                            {
                                switch (oper.OperType)
                                {
                                    case HoNClient.OPER_TYPE_FOUNDER:
                                        user.ImageIndex = 5;
                                        break;

                                    case HoNClient.OPER_TYPE_LEADER:
                                        user.ImageIndex = 4;
                                        break;

                                    case HoNClient.OPER_TYPE_OFFICER:
                                        user.ImageIndex = 3;
                                        break;
                                }
                            }
                        }
                    }

                    ChannelID[count] = e.ChannelID;

                    this.Invoke(new EventHandler(
                        delegate
                        {
                            radChannel[count].Text = e.ChannelName;
                            radChannel[count].Visible = true;
                            radChannel[count].Checked = true;
                        }));

                    CurrentChannel = count;
                    Program.Core.ChannelID = ChannelID[CurrentChannel];

                    txtChat[count].Invoke((MethodInvoker)(() => txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Now talking in channel '" + e.ChannelName + "' with " + e.UserCount + " users.")));

                    if (e.Topic != "")
                    {
                        this.Invoke(new EventHandler(
                            delegate
                            {
                                txtChat[count].AppendText(Environment.NewLine);
                                txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Topic is '" + e.Topic + "'");
                            }));
                    }

                    break;
                }
            }
        }

        void Core_onPlayerDemoted(object sender, PlayerDemotedEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    foreach (ListViewItem user in ChannelUsers[count].Items)
                    {
                        if ((UInt32)user.Tag == e.TargetID)
                        {
                            this.Invoke(new EventHandler(
                                delegate
                                {
                                    byte flags = Program.Core.GetFlags((UInt32)user.Tag);

                                    if (user.ImageIndex == 4)
                                    {
                                        user.ImageIndex = 3;

                                        txtChat[count].AppendText(Environment.NewLine);
                                        txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + e.TargetName + " has been demoted to Channel Officer by " + e.OperatorName);
                                    }
                                    else if (user.ImageIndex == 3)
                                    {
                                        if (Convert.ToBoolean(flags & HoNClient.USER_FLAG_PURCHASED))
                                        {
                                            user.ImageIndex = 2;
                                        }
                                        else
                                        {
                                            user.ImageIndex = 1;
                                        }

                                        txtChat[count].AppendText(Environment.NewLine);
                                        txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + e.TargetName + " has been demoted to No Admin Status by " + e.OperatorName);
                                    }

                                    if (count == CurrentChannel)
                                    {
                                        lstPlayers.Clear();
                                        lstPlayers.Columns.Add("", 165);

                                        foreach (ListViewItem clone in ChannelUsers[count].Items)
                                        {
                                            lstPlayers.Items.Add((ListViewItem)clone.Clone());
                                        }
                                    }
                                }));
                        }
                    }
                }
            }
        }

        void Core_onPlayerJoinedChannel(object sender, PlayerJoinedChannelEventArgs e)
        {
            ListViewItem user = new ListViewItem(e.User.Username);
            user.Tag = e.User.UserID;

            if (Convert.ToBoolean(e.User.Flags & HoNClient.USER_FLAG_S2))
            {
                switch (e.User.Status)
                {
                    case HoNClient.USER_STATUS_ONLINE:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(253, 0, 0);
                        user.ImageIndex = 4;
                        break;

                    case HoNClient.USER_STATUS_LOBBY:
                    case HoNClient.USER_STATUS_GAME:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(118, 0, 0);
                        user.ImageIndex = 4;
                        break;
                }
            }
            else if (Convert.ToBoolean(e.User.Flags & HoNClient.USER_FLAG_PURCHASED))
            {
                switch (e.User.Status)
                {
                    case HoNClient.USER_STATUS_ONLINE:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(53, 53, 53);
                        user.ImageIndex = 2;
                        break;

                    case HoNClient.USER_STATUS_LOBBY:
                    case HoNClient.USER_STATUS_GAME:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(53, 53, 53);
                        user.ImageIndex = 2;
                        break;
                }
            }
            else
            {
                switch (e.User.Status)
                {
                    case HoNClient.USER_STATUS_ONLINE:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(53, 53, 53);
                        user.ImageIndex = 1;
                        break;

                    case HoNClient.USER_STATUS_LOBBY:
                    case HoNClient.USER_STATUS_GAME:
                        user.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                        user.ForeColor = Color.FromArgb(53, 53, 53);
                        user.ImageIndex = 0;
                        break;
                }
            }

            for (int count = 1; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    if (count == CurrentChannel)
                    {
                        this.Invoke(new EventHandler(
                            delegate
                            {
                                if (btnChannel.Checked)
                                {

                                    foreach (HoNOper oper in ChannelOpers[e.ChannelID])
                                    {
                                        if (oper.OperID == e.User.UserID)
                                        {
                                            switch (oper.OperType)
                                            {
                                                case HoNClient.OPER_TYPE_FOUNDER:
                                                    user.ImageIndex = 5;
                                                    break;

                                                case HoNClient.OPER_TYPE_LEADER:
                                                    user.ImageIndex = 4;
                                                    break;

                                                case HoNClient.OPER_TYPE_OFFICER:
                                                    user.ImageIndex = 3;
                                                    break;
                                            }
                                        }
                                    }

                                    lstPlayers.Items.Add(user);
                                }

                                ChannelUsers[count].Items.Add((ListViewItem)user.Clone());
                            }));
                    }
                    else
                    {
                        ChannelUsers[count].Items.Add(user);
                    }

                    break;
                }
            }
        }

        void Core_onPlayerLeftChannel(object sender, PlayerLeftChannelEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    if (count == CurrentChannel)
                    {
                        this.Invoke(new EventHandler(
                            delegate
                            {
                                if (btnChannel.Checked)
                                {
                                    foreach (ListViewItem user in lstPlayers.Items)
                                    {
                                        if ((UInt32)user.Tag == e.UserID)
                                        {
                                            lstPlayers.Items.Remove(user);
                                            break;
                                        }
                                    }
                                }

                                foreach (ListViewItem user in ChannelUsers[count].Items)
                                {
                                    if ((UInt32)user.Tag == e.UserID)
                                    {
                                        ChannelUsers[count].Items.Remove(user);
                                        break;
                                    }
                                }
                            }));
                    }
                    else
                    {
                        this.Invoke(new EventHandler(
                            delegate
                            {
                                foreach (ListViewItem user in ChannelUsers[count].Items)
                                {
                                    if ((UInt32)user.Tag == e.UserID)
                                    {
                                        ChannelUsers[count].Items.Remove(user);
                                        break;
                                    }
                                }
                            }));
                    }

                    break;
                }
            }
        }

        void Core_onPlayerPromoted(object sender, PlayerPromotedEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    foreach (ListViewItem user in ChannelUsers[count].Items)
                    {
                        if ((UInt32)user.Tag == e.TargetID)
                        {
                            this.Invoke(new EventHandler(
                                delegate
                                {
                                    if (user.ImageIndex == 3)
                                    {
                                        user.ImageIndex = 4;

                                        txtChat[count].AppendText(Environment.NewLine);
                                        txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + e.TargetName + " has been promoted to Channel Leader by " + e.OperatorName);
                                    }
                                    else if (user.ImageIndex < 3)
                                    {
                                        user.ImageIndex = 3;

                                        txtChat[count].AppendText(Environment.NewLine);
                                        txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + e.TargetName + " has been promoted to Channel Officer by " + e.OperatorName);
                                    }

                                    if (count == CurrentChannel)
                                    {
                                        lstPlayers.Clear();
                                        lstPlayers.Columns.Add("", 165);

                                        foreach (ListViewItem clone in ChannelUsers[count].Items)
                                        {
                                            lstPlayers.Items.Add((ListViewItem)clone.Clone());
                                        }
                                    }
                                }));
                        }
                    }
                }
            }
        }

        void Core_onPluginConflict(object sender, PluginConflictEventArgs e)
        {
            MessageBox.Show(this, "A bot flag conflict over '" + e.ConflictingFlag + "' has occurred between the plug-ins '" + e.LoadedPlugin + "' and '" + e.ConflictingPlugin + "'. Only the plug-in '" + e.LoadedPlugin + "' will be loaded.", "NewerthBot");
        }

        void Core_onSendChannelMessage(object sender, SendChannelMessageEventArgs e)
        {
            for (int count = 1; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^444" + Program.Username + ": ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onSendClanMessage(object sender, SendClanMessageEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^458(Clan) " + Program.Username + ": ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onSendEmote(object sender, SendEmoteEventArgs e)
        {
            for (int count = 1; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^838[" + DateTime.Now.ToShortTimeString() + "]" + Program.Username + " " + e.Message);
                        }));
                }
            }
        }

        void Core_onSendInstantMessage(object sender, SendInstantMessageEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^940(IM to " + e.Username + ") ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onSendWhisper(object sender, SendWhisperEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^066(Whispered to " + e.Username + ") ^999" + e.Message);
                        }));
                }
            }
        }

        void Core_onSlashCommand(object sender, SlashCommandEventArgs e)
        {
            string[] parameters;

            switch (e.Command)
            {
                case "clan":
                case "c":
                    if (e.Parameters != "")
                    {
                        if (e.GetParameters(2, out parameters))
                        {
                            switch (parameters[0])
                            {
                                case "message":
                                case "m":
                                    Program.Core.SendClanMessage(parameters[1]);
                                    break;

                                case "invite":
                                case "i":
                                    Program.Core.SendClanInvite(parameters[1]);
                                    break;
                            }
                        }
                    }
                    break;

                case "emote":
                case "me":
                    if (e.Parameters != "")
                        Program.Core.SendEmote(ChannelID[CurrentChannel], Program.Username + " " + e.Parameters);
                    break;

                case "join":
                case "j":
                    if (e.Parameters != "")
                        if (!radChannel[8].Visible)
                            Program.Core.JoinChannel(e.Parameters);
                    break;

                case "whisper":
                case "w":
                    if (e.Parameters != "")
                    {
                        if (e.GetParameters(2, out parameters))
                        {
                            Program.Core.SendWhisper(parameters[0], parameters[1]);
                        }
                    }
                    break;
            }
        }

        void Core_onStatusUpdate(object sender, StatusUpdateEventArgs e)
        {
            ListViewItem lvi = null;
            ListView lv = null;
            bool currentChannel = false;
            bool foundUser = false;

            if (e.Status == HoNClient.USER_STATUS_OFFLINE)
            {
                for (int count = 1; count <= 8; count++)
                {
                    foreach (ListViewItem item in ChannelUsers[count].Items)
                    {
                        if ((UInt32)item.Tag == e.UserID)
                        {
                            lv = ChannelUsers[count];
                            break;
                        }
                    }
                }
            }

            this.Invoke(new EventHandler(
                delegate
                {
                    foreach (ListViewItem item in lstPlayers.Items)
                    {
                        if ((UInt32)item.Tag == e.UserID)
                        {
                            lvi = item;
                            currentChannel = true;
                            foundUser = true;
                            break;
                        }
                    }
                }));

            if (!foundUser)
            {
                for (int count = 1; count <= 8; count++)
                {
                    foreach (ListViewItem item in ChannelUsers[count].Items)
                    {
                        if ((UInt32)item.Tag == e.UserID)
                        {
                            lvi = item;
                            break;
                        }
                    }
                }
            }

            #region Channel
            if (lvi != null)
            {
                if (Convert.ToBoolean(e.Flags & HoNClient.USER_FLAG_S2))
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            switch (e.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(253, 0, 0);
                                    lvi.ImageIndex = 4;
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(118, 0, 0);
                                    lvi.ImageIndex = 4;
                                    break;

                                case HoNClient.USER_STATUS_OFFLINE:
                                    if (currentChannel)
                                    {
                                        lstPlayers.Items.Remove(lvi);
                                    }

                                    lv.Items.Remove(lvi);
                                    break;
                            }
                        }));
                }
                else if (Convert.ToBoolean(e.Flags & HoNClient.USER_FLAG_PURCHASED))
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            switch (e.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                    lvi.ImageIndex = 2;
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                    lvi.ImageIndex = 2;
                                    break;

                                case HoNClient.USER_STATUS_OFFLINE:
                                    if (currentChannel)
                                    {
                                        lstPlayers.Items.Remove(lvi);
                                    }

                                    lv.Items.Remove(lvi);
                                    break;
                            }
                        }));
                }
                else
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            switch (e.Status)
                            {
                                case HoNClient.USER_STATUS_ONLINE:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                    lvi.ImageIndex = 1;
                                    break;

                                case HoNClient.USER_STATUS_LOBBY:
                                case HoNClient.USER_STATUS_GAME:
                                    lvi.Font = new Font("Arial", 8.25F, FontStyle.Bold);
                                    lvi.ForeColor = Color.FromArgb(53, 53, 53);
                                    lvi.ImageIndex = 0;
                                    break;

                                case HoNClient.USER_STATUS_OFFLINE:
                                    if (currentChannel)
                                    {
                                        lstPlayers.Items.Remove(lvi);
                                    }

                                    lv.Items.Remove(lvi);
                                    break;
                            }
                        }));
                }
            }
            #endregion

            #region Buddy List
            HoNBuddy[] _buddies = BuddyList.ToArray();

            for (int count = 0; count <= _buddies.Length - 1; count++)
            {
                if (_buddies[count].UserID == e.UserID)
                {
                    _buddies[count].GameName = e.GameName;
                    _buddies[count].Server = e.GameServer;
                    _buddies[count].Status = e.Status;

                    BuddyList.Clear();
                    BuddyList.AddRange(_buddies);
                    break;
                }
            }
            #endregion

            #region Clan Roster
            HoNUser[] _members = ClanRoster.ToArray();

            for (int count = 0; count <= _members.Length - 1; count++)
            {
                if (_members[count].UserID == e.UserID)
                {
                    _members[count].Status = e.Status;

                    ClanRoster.Clear();
                    ClanRoster.AddRange(_members);
                    break;
                }
            }
            #endregion
        }

        void Core_onTopicChanged(object sender, TopicChangedEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (ChannelID[count] == e.ChannelID)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* Topic changed to '" + e.Topic + "'.");
                        }));
                    break;
                }
            }
        }

        void Core_onWhisper(object sender, WhisperEventArgs e)
        {
            for (int count = 0; count <= 8; count++)
            {
                if (radChannel[count].Visible)
                {
                    this.Invoke(new EventHandler(
                        delegate
                        {
                            txtChat[count].AppendText(Environment.NewLine);
                            txtChat[count].AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^099(Whisper from " + e.Username + ") ^999" + e.Message);
                        }));
                }
            }
        }
        #endregion

        void StatusMessage(string message)
        {
            txtStatus.AppendText(Environment.NewLine);
            txtStatus.AppendText("^770[" + DateTime.Now.ToShortTimeString() + "] ^145* " + message);
        }
    }

    public class ListViewSorter : IComparer
    {
        public int Compare(object x, object y)
        {
            ListViewItem xItem = (ListViewItem)x;
            ListViewItem yItem = (ListViewItem)y;
            int xIndex = xItem.ImageIndex;
            int yIndex = yItem.ImageIndex;

            if (xIndex == yIndex)
            {
                return 0;
            }
            else if (xIndex > yIndex)
            {
                return -1;
            }
            else if (xIndex < yIndex)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
    }
}